﻿using System;
using System.Web;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Common;
using log4net;
using AutoFacUtils;
using CashFlow.Admin.Def;
using CashFlow.Db.DAL;
using CashFlow.Db.Entity;
using CashFlow.Db.Repository;
using CashFlow.Admin.Service;
using CashFlow.Admin.Common;

namespace CashFlow.Admin.Service.Implement
{
    public class UserService : Service<UserInfoEntity>, IUserService
    {
        private static ILog _logger = LogManager.GetLogger(typeof(UserService));
        private IAdminService GetAdminService() { return AutoFacHelper.Get<IAdminService>(); }
        private IUserService GetUserService() { return AutoFacHelper.Get<IUserService>(); }
        private IShopService GetShopService() { return AutoFacHelper.Get<IShopService>(); }
        private IShopUserService GetShopUserService() { return AutoFacHelper.Get<IShopUserService>(); }

        public IList<UserInfoEntity> QueryAllChildUsersByUserId(int userId)
        {
            var ls = new List<UserInfoEntity>();

            var users = new List<UserInfoEntity>();
            using (var db = SqlSugarHelper.GetDb())
            {
                users = db.Queryable<UserInfoEntity>().ToList();
            }

            var self = users.Where(x => x.Id == userId).FirstOrDefault();
            if (self != null)
            {
                Queue<string> queue = new Queue<string>();
                queue.Enqueue(self.InvitationCode);
                ls.Add(self);
                while (queue.Count > 0)
                {
                    var item = queue.Dequeue();
                    var ls2 = users.Where(x => x.ReferenceInvitationCode == item).ToList();
                    foreach (var item2 in ls2)
                    {
                        queue.Enqueue(item2.InvitationCode);
                        ls.Add(item2);
                    }
                }
            }

            return ls;
        }

        public IList<UserInfoAndReferenceUserInfo> QueryAllChildUsersWithSameShopByUserId(
            int userId)
        {
            var ls = new List<UserInfoAndReferenceUserInfo>();

            var shopService = GetShopService();
            var shopInfo = shopService.QueryShopInfoByUserId(userId);
            var shopUserService = GetShopUserService();
            var shopUserIds = shopUserService.QueryShopAllUserIds(shopInfo.ShopManagerUserId);
            var users = new List<UserInfoEntity>();
            using (var db = SqlSugarHelper.GetDb())
            {
                users = db.Queryable<UserInfoEntity>().ToList();
            }

            var self = users.Where(x => x.Id == userId).FirstOrDefault();
            if (self != null)
            {
                Queue<string> queue = new Queue<string>();
                queue.Enqueue(self.InvitationCode);
                ls.Add(UserInfo_2_UserInfoAndReferenceUserInfo(self, users));
                while (queue.Count > 0)
                {
                    var item = queue.Dequeue();
                    var ls2 = users.Where(x => x.ReferenceInvitationCode == item).ToList();
                    foreach (var item2 in ls2)
                    {
                        if (shopUserIds.Contains(item2.Id))
                        {
                            queue.Enqueue(item2.InvitationCode);
                            ls.Add(UserInfo_2_UserInfoAndReferenceUserInfo(item2, users));
                        }
                    }
                }
            }

            ls = ls.OrderByDescending(x => x.UserInfo.CreateTime).ToList();

            return ls;
        }

        private UserInfoAndReferenceUserInfo UserInfo_2_UserInfoAndReferenceUserInfo(
            UserInfoEntity entity
            , IList<UserInfoEntity> users)
        {
            var item = users.Where(x => x.InvitationCode == entity.ReferenceInvitationCode)
                            .FirstOrDefault();
            return new UserInfoAndReferenceUserInfo
            {
                UserInfo = entity,
                ReferenceUserInfo = item
            };
        }

        public IList<UserInfoAndReferenceUserInfo> QueryAllChildUsersWithSameShopByUserIdByWhere(
            int userId
            , string phone
            , string name
            , string invitationCode
            , string reference
            , string referenceInvitationCode)
        {
            var ls = QueryAllChildUsersWithSameShopByUserId(userId);
            if (!string.IsNullOrEmpty(phone))
            {
                ls = ls.Where(x => x.UserInfo.Phone.Contains(phone)).ToList();
            }
            if (!string.IsNullOrEmpty(name))
            {
                ls = ls.Where(x => x.UserInfo.Name.Contains(name)).ToList();
            }
            if (!string.IsNullOrEmpty(invitationCode))
            {
                ls = ls.Where(x => x.UserInfo.InvitationCode.Contains(invitationCode)).ToList();
            }
            if (!string.IsNullOrEmpty(reference))
            {
                ls = ls.Where(x => x.ReferenceUserInfo.Name.Contains(reference)).ToList();
            }
            if (!string.IsNullOrEmpty(referenceInvitationCode))
            {
                ls = ls.Where(x => x.UserInfo.ReferenceInvitationCode.Contains(referenceInvitationCode)).ToList();
            }

            return ls;
        }

        public IList<UserInfoEntity> QueryMyCustomers(int userId)
        {
            var userService = GetUserService();
            var ui = userService.QuerySingleById(userId);
            using (var db = SqlSugarHelper.GetDb())
            {
                var ls = db.Queryable<UserInfoEntity>()
                            .Where(x => x.ReferenceInvitationCode == ui.InvitationCode)
                            .ToList();
                return ls;
            }
        }

        public IList<UserInfoEntity> QueryMyCustomers()
        {
            var adminService = GetAdminService();
            var ui = adminService.GetLoginUserInfo();
            return QueryMyCustomers(ui.ShopManagerUserId);
        }

        public EUpdateUserResult UpdateUser(int userId
            , string phone
            , string name)
        {
            EUpdateUserResult result = EUpdateUserResult.Other;

            using (var db = SqlSugarHelper.GetDb())
            {
                int n = db.Queryable<UserInfoEntity>()
                            .Where(x => x.Phone == phone && x.Id != userId)
                            .Count();
                if (n > 0)
                {
                    result = EUpdateUserResult.ExistPhone;
                }
                else
                {
                    var entity = new UserInfoEntity
                    {
                        Id = userId
                    };
                    db.Tracking(entity);
                    entity.Phone = phone;
                    entity.Name = name;
                    int n2 = db.Updateable<UserInfoEntity>(entity).ExecuteCommand();
                    if (n2 > 0)
                    {
                        result = EUpdateUserResult.Success;
                    }
                }
            }

            if (result != EUpdateUserResult.Success)
            {
                string text = string.Format("Update User Fail, result: {0}, userId = {1}, phone = {2}, name = {3}"
                    , (int)result
                    , userId
                    , phone
                    , name);
                _logger.Error(text);
            }

            return result;
        }

        public EResetUserPwdResult ResetPwd(int userId
            , string pwd
            , string newPwd)
        {
            EResetUserPwdResult result = EResetUserPwdResult.Other;

            using (var db = SqlSugarHelper.GetDb())
            {
                var entity = db.Queryable<UserInfoEntity>()
                            .Where(x => x.Id == userId && x.Password == pwd)
                            .First();
                if (entity != null && entity.Id > 0)
                {
                    db.Tracking(entity);
                    entity.Password = newPwd;
                    int n = db.Updateable(entity).ExecuteCommand();
                    if (n > 0)
                    {
                        result = EResetUserPwdResult.Success;
                    }
                }
                else
                {
                    result = EResetUserPwdResult.PwdError;
                }
            }

            if (result != EResetUserPwdResult.Success)
            {
                string text = string.Format("Reset User Pwd Fail, Result: {0} UserId = {1}, Pwd = {2}, NewPwd = {3}"
                                , (int)result
                                , userId
                                , pwd
                                , newPwd);
                _logger.Error(text);
            }

            return result;
        }
    }
}